/**
 *
 * @param {{
 *  canvas: HTMLCanvasElement
 *  width: number
 *  height: number
 * }} input
 * @returns
 */
export async function process(input) {
  const canvas = input.canvas
  const width = input.width
  const height = input.height

  const ctx = canvas.getContext('2d')

  const eWidth = Math.floor(width % 8 === 0 ? width / 8 : width / 8 + 1)
  let currentHeight = 0
  let index = 0
  const area = height * eWidth
  const bytes = [] // the bytes length is equals `area`
  for (let b1 = 0; b1 < area; b1++) {
    bytes[b1] = 0
  }
  const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)

  while (currentHeight < height) {
    // let rowData = []; // the row data length is image height
    let eightBitIndex = 0
    for (let x = 0; x < width; x++) {
      eightBitIndex++
      if (eightBitIndex > 8) {
        eightBitIndex = 1
        index++
      }
      const n = 1 << (8 - eightBitIndex)

      // const pixel = ctx.getImageData(x, currentHeight, 1, 1);
      const pixels = fastExtractPixel(imgData, x, currentHeight, 1, 1)
      const pixel = pixels[0]
      // const rgba = pixel.data;
      const red = pixel[0]
      const green = pixel[1]
      const blue = pixel[2]
      if ((red + green + blue) / 3 < 128) {
        bytes[index] = bytes[index] | n
      }
    }
    index = eWidth * (currentHeight + 1)
    currentHeight += 1
  }

  return new Uint8Array(bytes)
}

function fastExtractPixel(imageData, x, y, w, h) {
  let i, j
  const result = []
  let r, g, b, a
  const data = imageData.data

  for (j = 0; j < h; j++) {
    let idx = (x + (y + j) * imageData.width) * 4 // get left most byte index for row at y + j
    for (i = 0; i < w; i++) {
      r = data[idx++]
      g = data[idx++]
      b = data[idx++]
      a = data[idx++]
      // do the processing
      result.push([r, g, b, a])
    }
  }
  return result
}
